package com.example.springbootlocal.utils;

import java.lang.reflect.Field;

/**
 * @author X.I.O
 * @title: ReflectUtils
 * @projectName spring-boot-local
 * @description: TODO
 * @date 2021/11/9 23:12
 */
public class ReflectUtils {

    /**
     * 获取对象的属性
     * @param t 对象
     * @param name 属性名
     * @param <T> 泛型
     * @return  属性
     */
    public static <T> Field getFieldByName(T t, String name){
        Field[] fields=getFields(t);
        for (int i = 0; i < fields.length; i++) {
            Field field=fields[i];
            String fieldName=field.getName().toLowerCase();
            name=name.toLowerCase();
            if(fieldName.equals(name)){
                return field;
            }
        }
        return null;
    }

    /**
     * 获取对象的反射类
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Class<T> getClass(T t){
        Class<T> tClass=(Class<T>) t.getClass();
        return tClass;
    }

    /**
     * 通过反射类获取属性列表
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> Field[] getFields(Class<T> cls){
        Field[] fields=cls.getDeclaredFields();
        return fields;
    }

    /**
     * 通过对象获取属性列表
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Field[] getFields(T t){
        Class<T> tClass=getClass(t);
        return getFields(tClass);
    }

    /**
     * 通过属性获取对象的值
     * @param t  对象
     * @param field 属性
     * @param <T>  对象泛型
     * @return  值
     * @throws Exception
     */
    public static<T> Object getObjectByField(T t,Field field) throws Exception{
        field.setAccessible(true);
        Object val=field.get(t);
        return val;
    }

    /**
     * 通过属性设置 对象的值
     * @param field 属性
     * @param t  对象
     * @param value  值
     * @param <T> 对象泛型
     * @throws Exception
     */
    public static <T> void setObjectByField(Field field,T t,Object value) throws Exception{
        field.setAccessible(true);
        field.set(t,value);
    }

    /**
     * 通过属性名设置对象的值
     * @param fieldName  属性名
     * @param t  对象
     * @param value  值
     * @param <T> 对象泛型
     * @throws Exception
     */
    public static <T> void setObjectByFieldName(String fieldName,T t,Object value) throws Exception{
        Field field=getFieldByName(t,fieldName);
        if(field==null){
            return;
        }
        setObjectByField(field,t,value);
    }

    /**
     * 通过属性名，获取值
     * @param fieldName 属性名
     * @param t 对象
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> Object getObjectByFieldName(String fieldName,T t) throws Exception{
        Field field=getFieldByName(t,fieldName);
        return getObjectByField(t,field);
    }

    /**
     * 通过属性名模糊搜索，返回对应的属性
     * @param t  对象
     * @param name  属性名
     * @param <T>  泛型
     * @return  属性
     * @throws Exception
     */
    public static <T> Field getFieldByLikeName(T t,String name) throws Exception{
        Field[] fields=getFields(t);
        for (int i = 0; i < fields.length ; i++) {
            Field field=fields[i];
            String fieldName = field.getName().toLowerCase();
            name=name.toLowerCase();
            if(fieldName.contains(name)){
                return field;
            }
        }
        return null;
    }


    /**
     * 将source 对象的值赋值给 target
     * @param source
     * @param target
     * @param <T>
     * @return
     */
    public static <T> T copyBeanUtils(T source,T target) throws IllegalAccessException{
        Field[] targetFields=getFields(target);
        for (int i = 0; i < targetFields.length; i++) {
            Field field=targetFields[i];
            field.setAccessible(true);
            Object value=field.get(source);
            field.set(target,value);
        }
        return target;
    }
}
